//
//  BLECenterManager.swift
//  BLE-Center
//
//  Created by WZ on 2018/2/3.
//  Copyright © 2018年 xcamera. All rights reserved.
//

import UIKit
import CoreBluetooth

//let kBLEService_UUID = "00001808-0000-1000-8000-00805f9b34fb" //服务UUID
//let kBLE_Characteristic_uuid_Rx = "00002a6d-0000-1000-8000-00805f9b34fb" //读UUID 工作状态
//let kBLE_Characteristic_uuid_Rv = "00002a18-0000-1000-8000-00805f9b34fb" //读UUID  结果数据

let WZServeUUID = "00001808-0000-1000-8000-00805f9b34fb"//"10086"
let WZCharaUUID = "00002a6d-0000-1000-8000-00805f9b34fb"//"10000"

class BLECenterManager: NSObject
{
    
    /// 获取单例
    static let shared = BLECenterManager()

    /// 私有属性: 中心设备管理者
    fileprivate lazy var mger = CBCentralManager(delegate: self, queue: DispatchQueue.main, options:[CBCentralManagerOptionShowPowerAlertKey : true]) //系统设置中蓝牙选项没打开时自动弹框
    
    /// 中心设备发现的外设(必须对其进行强引用，否则会自动断开连接)
    fileprivate var peripheral : CBPeripheral?
    
    ///外设发现某个服务下的某个特征值
    fileprivate var chara : CBCharacteristic?
    
    
    /// 将初始化方法变为私有，防止别人再次调用来创建
    private override init() {
        super.init()
    }
    
    func createCentralManagerAndBeginScan() -> Void {
        if mger.isScanning { //此处会调用懒加载，创建mger
            mger.stopScan()
        }
    }
    
    
}


// MARK: - 原类遵守协议用,号分割，分类遵守协议用:分开
extension BLECenterManager : CBCentralManagerDelegate
{
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        //self.showText(#function + "中心设备状态(0:未知 1:正在重置 2:不支持蓝牙 3:未认证 4:未开机 5:正常)，当前:" + String(central.state.rawValue) )
        //String语法糖
//        self.showText(#function + "中心设备状态(0:未知 1:正在重置 2:不支持蓝牙 3:未认证 4:未开机 5:正常)，当前: \(central.state.rawValue) ")
        
        //开始扫描外设的服务(数组中)
        if central.state == .poweredOn {
            //必须在开机时扫描，否则报错: [CoreBluetooth] API MISUSE: <CBCentralManager: 0x1019be380> can only accept this command while in the powered on state
            central.scanForPeripherals(withServices: [CBUUID(string: WZServeUUID)], options: nil)
        } else {
            
            if central.state.rawValue == 5 {
                central.scanForPeripherals(withServices: [CBUUID(string: WZServeUUID)], options: nil)
            }else{
                UIAlertController.showAlertController(style: .alert, title: "蓝牙设备无法使用", message: "(0:未知 1:正在重置 2:不支持蓝牙 3:未认证 4:未开机 5:正常), 当前:\(central.state.rawValue)", okActionTitle: "确定", okAction: nil, cancelActionTitle: nil, cancelAction: nil)
            }
        }
    }
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { //设备与手机之间的距离公式大概如下: powe(10, (abs(rssi) - 59) / (10 * 2.0)); 大概有这么一个关系，不是很准确。
        
        //if (peripheral.name ?? "").hasPrefix("iPhone") {
        if (peripheral.name ?? "") != "Sjcam-test" {
            //显示中心设备 和 外设 信息
            self.showText("\n中心设备:" + central.debugDescription + "\n发现了外设:" + peripheral.debugDescription + "\n广播字典:" + advertisementData.debugDescription + "\n信号强度:" + String(RSSI.intValue) )
            
            //连接外设前必须对其强引用，否则报错:[CoreBluetooth] API MISUSE: Cancelling connection for unused peripheral <CBPeripheral: 0x101888da0, identifier = F2CD049C-F566-8703-3D9A-9F3B3D4F4F84, name = iPhone, state = connecting>, Did you forget to keep a reference to it?
            self.peripheral = peripheral
            //连接外设
            central.connect(peripheral, options: nil)
        }
        
    }
    

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        self.showText("中心设备连接外设成功")
        //中心设备管理者任务完成了，剩下的事情由外设来做
        central.stopScan()
        
        //设为外设的代理
        peripheral.delegate = self
        //让外设去发现服务
        peripheral.discoverServices([CBUUID(string: WZServeUUID)])
    }
    
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        self.showText("中心设备连接外设失败,err:" + error.debugDescription)
    }
    
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        self.showText("中心设备断开了外设的连接")
        // 断开连接可以设置重新连接
        central.connect(peripheral, options: nil)
    }
    
    
}
//找到周边服务
extension BLECenterManager : CBPeripheralDelegate {
//    找到服务
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        
        self.showText("外设发现了自己的服务，err:" + error.debugDescription)
        
        //让外设去发现各个服务中的各个特征
        /* 以下写法大错特错：以下相当于创建了一个新的服务，然后让当前已经连接的外设 去发现 这个新创建的服务
        let service = CBMutableService(type: CBUUID(string: WZServeUUID), primary: true)
        peripheral.discoverCharacteristics([CBUUID(string: WZCharaUUID)], for: service)
        */
        
        //正确的做法是: 让当前已经连接的外设 去 发现 自带的服务
        let service = (peripheral.services?.first)!   //发现外设自带的服务，而不是自己创建的服务(不同的对象)
        peripheral.discoverCharacteristics([CBUUID(string: WZCharaUUID)], for: service)
    }
//    找到特征
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        self.showText("外设发现某个服务:" + service.uuid.uuidString + "的所有特征！ err:" + error.debugDescription ) //执行到这

        guard let chara = service.characteristics?.first else {
            self.showText("服务的特征为空")
            return }
        
        //记录特征
        self.chara = chara
        
        //利用特征发送一条数据
        peripheral.readValue(for: chara)
        peripheral.setNotifyValue(true, for: chara)
        
        peripheral.writeValue("我是中心设备".data(using: .utf8)!, for: chara, type: .withResponse)
    }
    
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        let data = characteristic.value ?? Data()
        let str = String(data: data, encoding: .utf8) ?? ""
        self.showText(#function + "---" + str)
    }
    
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        let data = characteristic.value ?? Data()
        let str = String(data: data, encoding: .utf8) ?? ""
        self.showText(#function + "---" + str)
    }
    
    func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
        let data = characteristic.value ?? Data()
        let str = String(data: data, encoding: .utf8) ?? ""
        self.showText(#function + "---" + str)
    }
    
    func peripheralDidUpdateName(_ peripheral: CBPeripheral) {
        self.showText(#function + (peripheral.name ?? "") )
    }
}

extension BLECenterManager {
    
    func showText(_ str:String) -> Void {
        let txtView = RootVC?.view.viewWithTag(6666) as? UITextView
        txtView?.text = (txtView?.text ?? "") + "\n\n" + str
        print(txtView?.text ?? "")
    }
    
}

